<template>
	<el-drawer
	  v-model="dialog.visible"
	  :title="dialog.title"
	  append-to-body
	  @close="closeDialog"
	  :close-on-click-modal="false"
	  size="750"
	>
		
		<el-form
			ref="formRef"
			:model="formData"
			:rules="formRules"
			label-width="130px"
		>
			
			<el-form-item label="参数名" prop="name">
				<el-input v-model="formData.name" placeholder="请输入参数名" />
			</el-form-item>
			
			<el-form-item label="参数标识" prop="identifier" v-if="showReplaceContent==true">
				<el-input v-model="formData.identifier" placeholder="请输入参数标识" />
			</el-form-item>
			
			<el-form-item label="参数字段" prop="identifier" v-else>
			  <el-input 
			    v-model="formData.identifier" 
			    placeholder="请输入字段路径，例如: data.list[0].name" 
			  >
			    <template #append>
			      <el-tooltip content="支持多级路径，使用.分隔，数组使用[index]表示" placement="top">
			        <el-icon><QuestionFilled /></el-icon>
			      </el-tooltip>
			    </template>
			  </el-input>
			</el-form-item>
			
			<el-form-item label="参数类型" prop="type" >
				<Dict v-model="formData.type" code="field_type" />
			</el-form-item>
			
			<el-form-item label="参数匹配" prop="replaceContent" v-if="showReplaceContent">
				<el-input v-model="formData.replaceContent" placeholder="请输入参数匹配内容" />
			</el-form-item>
			
			<el-form-item label="参数值来源" prop="fieldValueFormSrc"  >
				<el-radio-group v-model="formData.fieldValueFormSrc" @change="handleFieldValueFormSrcChange">
					<el-radio value="input">输入</el-radio>
					<el-radio value="OLTP" >OLTP</el-radio>
					<el-radio value="redis" >缓存(Redis)</el-radio>
					<el-radio value="constant" >常量</el-radio>
					<el-radio value="uuid" >uuid</el-radio>
					<el-radio value="curSystemDate" v-if="['dateString','long','timestampString'].includes(formData.type)">系统时间</el-radio>
				</el-radio-group>
			</el-form-item>
			
			<el-form-item label="日期格式" prop="dateFieldFormatSrc" v-if="['dateString'].includes(formData.type)">
				<el-radio-group v-model="formData.dateFieldFormatSrc" class="flex-container">
					<el-radio value="input">自定义</el-radio>
					<el-radio value="select">下拉选择日期格式</el-radio>
				</el-radio-group>
			</el-form-item>
			
			<el-form-item label="日期格式" prop="dateFieldFormat" v-if="['dateString'].includes(formData.type)">
				<el-select
					v-model="formData.dateFieldFormat"
					placeholder="请选择输出日期格式"
					v-if="formData.dateFieldFormatSrc=='select'"
				>
					<el-option label="yyyy-MM-dd" value="yyyy-MM-dd" />
					<el-option label="yyyy-MM-dd HH:mm:ss" value="yyyy-MM-dd HH:mm:ss" />
					<el-option label="yyyy年MM月dd日" value="yyyy年MM月dd日" />
					<el-option label="yyyy年MM月dd日 HH时mm分ss秒" value="yyyy年MM月dd日 HH时mm分ss秒" />
					<el-option label="HH:mm:ss" value="HH:mm:ss" />
					<el-option label="HH时mm分ss秒" value="HH时mm分ss秒" />
					<el-option label="yyyy/MM/dd" value="yyyy/MM/dd" />
					<el-option label="yyyy/MM/dd HH:mm:ss" value="yyyy/MM/dd HH:mm:ss" />
					<el-option label="yyyyMMdd" value="yyyyMMdd" />
					<el-option label="yyyyMMddHHmmss" value="yyyyMMddHHmmss" />
				</el-select>
				<el-input v-model="formData.dateFieldFormat" placeholder="请输入日期格式" v-else />
			</el-form-item>
			
			
			<el-form-item label="缓存标识" prop="redisKey" v-if="formData.fieldValueFormSrc=='redis'">
				<el-input v-model="formData.redisKey" placeholder="请输入缓存标识" />
			</el-form-item>
			
			<el-form-item label="OLTP数据源" prop="datasourceId" v-if="formData.fieldValueFormSrc=='OLTP'" >
				<el-select v-model="formData.datasourceId" >
					<el-option
					  v-for="item in datasourceOptions"
					  :key="item.id"
					  :label="item.name"
					  :value="item.id"
					/>
				</el-select>
			</el-form-item>
			
			<el-form-item label="取值SQL" prop="sql" v-if="formData.fieldValueFormSrc=='OLTP'">
				<div style="display: flex;flex-direction: column;width: 100%;">
					<MonacoEditor
					  v-model="formData.sql"
					  :options="sqlEditorOptions"
					  language="sql"
					  style="height: 200px;"
					  @change="validateSQL"
					/>
					
					<div class="sql-tips">
					  <el-alert
						title="SQL编写提示"
						type="info"
						:closable="false"
					  >
						<template #default>
						  <p>1. SQL语句必须以SELECT开头</p>
						  <p>2. SQL必须包含参数标识字段: {{ formData.identifier?.split('.').pop() }}</p>
						  <p>3. 查询结果的字段名必须与参数标识字段匹配</p>
						</template>
					  </el-alert>
					</div>
				</div>
			</el-form-item>
			
			<el-form-item label="参数必填" prop="required" >
			  <el-radio-group v-model="formData.required" @change="handleRequiredChange" :disabled="['constant','uuid'].includes(formData.fieldValueFormSrc)">
			    <el-radio value="0">可选</el-radio>
			    <el-radio value="1">必填</el-radio>
			  </el-radio-group>
			</el-form-item>
			
			<el-form-item label="保留小数位" prop="fieldDecimalPoint" v-if="['float','double'].includes(formData.type)">
				<el-input-number v-model="formData.fieldDecimalPoint" placeholder="请输入字段保留小数位" :min="0" :max="32" style="width: 100%;" />
			</el-form-item>
			
			<el-form-item label="参数默认值" prop="defaultValue">
				<el-select v-model="formData.defaultValue" placeholder="请选择默认值" v-if="formData.type=='boolean'">
				  <el-option label="true" :value="true" />
				  <el-option label="false" :value="false" />
				</el-select>
				<el-input-number v-model="formData.defaultValue" :min="0" v-else-if="formData.type=='int'" />
				<el-input v-model="formData.defaultValue" placeholder="请输入参数默认值" v-else />
			</el-form-item>
		</el-form>
	
		<template #footer>
		  <div class="dialog-footer">
			<el-button @click="showJsonParseDialog = true && showReplaceContent!=true" :loading="loading">解析JSON结构</el-button>
			<el-button type="primary" @click="submitForm" :loading="loading">确 定</el-button>
			<el-button @click="closeDialog" :loading="loading">取 消</el-button>
		  </div>
		</template>
		
		<!-- JSON解析弹窗 -->
		<el-dialog
		  v-model="showJsonParseDialog"
		  title="解析JSON结构"
		  width="600px"
		  append-to-body
		>
		  <el-form>
		    <el-form-item>
		      <MonacoEditor
		        v-model="jsonContent"
		        :options="jsonEditorOptions"
		        language="json"
		        style="height: 300px;"
		      />
		    </el-form-item>
		  </el-form>
		  <template #footer>
		    <div class="dialog-footer">
		      <el-button @click="showJsonParseDialog = false">取 消</el-button>
		      <el-button type="primary" @click="handleParseJson">解 析</el-button>
		    </div>
		  </template>
		</el-dialog>
		
	</el-drawer>
</template>

<script lang="ts" setup>
	import { ref } from "vue";
	import type {FormRules } from 'element-plus'
	import { ElMessage } from "element-plus";
	import { reactive } from "vue";
	import { onMounted } from "vue";
	import DatasourceAPI from "@/api/biz/datasource";
	import MonacoEditor from '@/components/MonacoEditor/index.vue'
	// import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
	// import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
	// import sqlWorker from 'monaco-editor/esm/vs/language/sql/sql.worker?worker';
	// import 'monaco-editor/esm/vs/basic-languages/sql/sql.contribution';
	const emit = defineEmits(['success', 'closed', 'parse-fields']);
	const loading = ref(false);
	const validateSQL = (_rule: any, value: string | undefined, callback: any): void => {
	  if ((!value || value.trim() === '') && formData.value.fieldValueFormSrc === 'OLTP') {
	    callback(new Error('请输入SQL语句'));
	    return;
	  }
	  
	  if (value && formData.value.fieldValueFormSrc === 'OLTP') {
	    // 检查是否包含参数标识字段
	    const identifier = formData.value.identifier;
	    const columnName = identifier.split('.').pop(); // 获取最后一段作为字段名
	    
	    // SQL 必须以 SELECT 开头
	    if (!value.trim().toLowerCase().startsWith('select')) {
	      callback(new Error('SQL语句必须以SELECT开头'));
	      return;
	    }
	    
	    // 检查是否包含参数标识字段
	    const hasIdentifier = value.toLowerCase().includes(columnName.toLowerCase());
	    if (!hasIdentifier) {
	      callback(new Error(`SQL语句必须包含参数标识字段: ${columnName}`));
	      return;
	    }
	  }
	  
	  callback();
	};
	const dialog = ref({
		visible:false,
		title:'',
	});
	const showJsonParseDialog = ref(false);
	const jsonContent = ref('');
	const rowIndex = ref<number>(1);
	const formRef=ref();
	const formRules=reactive<FormRules>({
		name: [
			{ required: true, message: "请输入参数名", trigger: "blur" }
		],
		identifier: [
			{ required: true, message: "请输入参数标识", trigger: "blur" }
		],
		type: [
			{ required: true, message: "请选择输入参数类型", trigger: "change" }
		],
		replaceContent: [
			{ required: true, message: "请选择输入Sql替换内容", trigger: "change" }
		],
		required: [
			{ required: true, message: "请选择参数是否必填", trigger: "change" }
		],
		dataFormat: [
			{ required: true, message: "请选择参数日期格式", trigger: "change" }
		],
		fieldValueFormSrc: [
			{ required: true, message: "请选择日期参数源", trigger: "change" }
		],
		datasourceId: [
			{ required: true, message: "请选择数据源", trigger: "change" }
		],
		sql: [
			{ validator: validateSQL, trigger: 'blur' }
		],
		redisKey: [
			{ required: true, message: "请输入缓存标识", trigger: "change" }
		],
		fieldDecimalPoint: [
			{ required: true, message: "请输入保留小数点", trigger: "change" }
		],
		dateFieldFormatSrc: [
			{ required: true, message: "请选择日期格式定义方式", trigger: "change" }
		],
		dateFieldFormat: [
			{ required: true, message: "请输入日期格式", trigger: "change" }
		],
	});
	
	//数据源下拉框
	const datasourceOptions=ref<any>([]);
	
	//数据源
	const formData=ref<any>({
		sql: '',
	});
	
	const getOLTPDatasources= async ()=>{
		try {
			const data = await DatasourceAPI.options({});
			datasourceOptions.value = data.map((item:any) => ({
				id: item.id,
				name: item.name
			}));
		} catch (error:any) {
			console.error(error)
			ElMessage.error('获取OLTP下拉数据失败');
		}
	}
	
	const handleRequiredChange=()=>{
		if(formData.value.required=='1'){
			formRules["defaultValue"]=[
				{ required: true, message: "默认值必填.", trigger: "change" }
			]
		}else{
			delete formRules?.defaultValue
		}
	}
	
	const handleFieldValueFormSrcChange=()=>{
		if(formData.value.fieldValueFormSrc=='constant'){
			formData.value.required='1';
			handleRequiredChange();
		}
		else if(formData.value.fieldValueFormSrc=='uuid'){
			formData.value.required='1';
		}
	}
	
	const handleParseJson = () => {
	  try {
	    const jsonObj = JSON.parse(jsonContent.value);
	    const fields = parseJsonStructure(jsonObj);
	    emit('parse-fields', fields);
	    showJsonParseDialog.value = false;
	    jsonContent.value = '';
	  } catch (error) {
	    ElMessage.error('JSON格式不正确，请检查输入');
	  }
	};
	
	const parseJsonStructure = (obj: any, parentPath = ''): any[] => {
	  const fields: any[] = [];
	  
	  for (const key in obj) {
	    const value = obj[key];
	    const currentPath = parentPath ? `${parentPath}.${key}` : key;
	    
	    // 根据值类型确定字段类型
	    let fieldType: string;
	    let defaultValue: any = '';
	    
	    if (Array.isArray(value)) {
	      fieldType = 'array'; // 数组
	      defaultValue = JSON.stringify(value);
	      if (value.length > 0) {
	        fields.push(...parseJsonStructure(value[0], `${currentPath}[0]`));
	      }
	    } else if (value === null) {
	      fieldType = 'string'; // 字符串
	    } else if (typeof value === 'object') {
	      fieldType = 'object'; // 对象
	      defaultValue = JSON.stringify(value);
	      fields.push(...parseJsonStructure(value, currentPath));
	    } else if (typeof value === 'number') {
	      // 根据数值特征判断具体数字类型
	      if (Number.isInteger(value)) {
	        if (value > 2147483647) {
	          fieldType = 'long'; // 长整型
	        } else {
	          fieldType = 'int'; // 整型
	        }
	      } else {
	        // 判断是否需要双精度
	        if (Math.abs(value) > 3.4e38 || value.toString().split('.')[1]?.length > 7) {
	          fieldType = 'double'; // 双精度
	        } else {
	          fieldType = 'float'; // 单精度
	        }
	      }
	    } else if (typeof value === 'boolean') {
	      fieldType = 'boolean'; // 布尔
	    } else if (value instanceof Date) {
	      // 根据需求选择合适的日期类型
	      if (value.getHours() === 0 && value.getMinutes() === 0 && value.getSeconds() === 0) {
	        fieldType = 'date'; // 日期
	      } else {
	        fieldType = 'dateString'; // 日期字符串
	      }
	    } else {
	      // 默认为字符串类型
	      fieldType = 'string';
	      defaultValue = value;
	    }
	    
	    fields.push({
	      name: key,
	      identifier: currentPath,
	      type: fieldType,
	      fieldValueFormSrc: 'input',
	      defaultValue,
	      required: '0',
	      description: ''
	    });
	  }
	  
	  return fields;
	};
	
	const showReplaceContent=ref<boolean>(false)
	async function openDialog(index: number,_row?: any, type?: string,replace?:boolean) {
		getOLTPDatasources();
		showReplaceContent.value=replace||false
		if('add'==type){
			rowIndex.value=index;
			dialog.value.visible=true;
			dialog.value.title='新增参数';
		}else{
			rowIndex.value=index;
			dialog.value.visible=true;
			dialog.value.title='编辑参数';
			formData.value=_row?JSON.parse(JSON.stringify(_row)):[];
			handleRequiredChange();
		}
	}
	
	const submitForm=()=>{
		formRef.value.validate((isValid: boolean) => {
			if (isValid) {
				loading.value = true;
				emit('success', rowIndex.value, JSON.parse(JSON.stringify(formData.value)));
				loading.value = false;
				closeDialog();
			}
		});
	}
	
	const closeDialog=()=>{
		dialog.value.visible=false;
		dialog.value.title="";
		emit('closed')
		resetForm();
	}
	
	/**
	 * 重置表单
	 */
	function resetForm() {
		formRef.value.resetFields();
		formRef.value.clearValidate();
		formData.value={};
	}	
	
	defineExpose({
	  openDialog,closeDialog
	});
	
	onMounted(() => {
	});
	
	const jsonEditorOptions = {
	  theme: 'vs-dark',
	  language: 'json',
	  automaticLayout: true,
	  minimap: { enabled: false },
	  lineNumbers: 'on',
	  folding: true,
	  wordWrap: 'on',
	  fontSize: 14,
	  tabSize: 2,
	  formatOnPaste: true,
	  formatOnType: true,
	};
	
	const sqlEditorOptions = {
	  theme: 'vs-dark',
	  language: 'sql',
	  automaticLayout: true,
	  minimap: { enabled: false },
	  lineNumbers: 'on',
	  folding: true,
	  wordWrap: 'on',
	  fontSize: 14,
	  tabSize: 2,
	  formatOnPaste: true,
	  formatOnType: true,
	  suggestOnTriggerCharacters: true,
	  quickSuggestions: true,
	};
</script>

<style scoped>
	.step-content{
		background-color: aliceblue;
		margin-top: 8px;
		padding: 8px;
		padding-top: 16px;
	}
	
	.sql-tips {
	  margin-top: 8px;
	}
	
	:deep(.el-alert__content) {
	  p {
	    margin: 4px 0;
	    font-size: 12px;
	    color: #666;
	  }
	}
</style>